package vues;
/*
 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 * 
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 * 
 */


import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.Printable;
import java.io.File;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Map.Entry;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;

import logique.reseau.Troncon;
import logique.reseau.Ville;
import controleur.Controleur;
import edu.uci.ics.jung.graph.ArchetypeVertex;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.decorators.EdgeShape;
import edu.uci.ics.jung.graph.decorators.EllipseVertexShapeFunction;
import edu.uci.ics.jung.graph.decorators.VertexIconAndShapeFunction;
import edu.uci.ics.jung.graph.decorators.VertexStringer;
import edu.uci.ics.jung.graph.impl.AbstractSparseEdge;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.graph.impl.SparseGraph;
import edu.uci.ics.jung.graph.impl.SparseVertex;
import edu.uci.ics.jung.graph.impl.UndirectedSparseEdge;
import edu.uci.ics.jung.visualization.AbstractLayout;
import edu.uci.ics.jung.visualization.DefaultGraphLabelRenderer;
import edu.uci.ics.jung.visualization.DefaultSettableVertexLocationFunction;
import edu.uci.ics.jung.visualization.FRLayout;
import edu.uci.ics.jung.visualization.PluggableRenderer;
import edu.uci.ics.jung.visualization.StaticLayout;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.ScalingControl;
/**
 * Shows how easy it is to create a graph editor with JUNG.
 * Mouse modes and actions are explained in the help text.
 * The application version of GraphEditorDemo provides a
 * File menu with an option to save the visible graph as
 * a jpeg file.
 * 
 * @author Tom Nelson - RABA Technologies
 * 
 */
public class MiniGraph implements Printable {

    /**
     * the graph
     */
    Graph graph;
    
    AbstractLayout layout;

    /**
     * the visual component and renderer for the graph
     */
    VisualizationViewer vv;
    
    DefaultSettableVertexLocationFunction vertexLocations;
    Container content;
    String instructions =
        "<html>"+
        "<h3>All Modes:</h3>"+
        "<ul>"+
        "<li>Right-click an empty area for <b>Create Vertex</b> popup"+
        "<li>Right-click on a Vertex for <b>Delete Vertex</b> popup"+
        "<li>Right-click on a Vertex for <b>Add Edge</b> menus <br>(if there are selected Vertices)"+
        "<li>Right-click on an Edge for <b>Delete Edge</b> popup"+
        "<li>Mousewheel scales with a crossover value of 1.0.<p>"+
        "     - scales the graph layout when the combined scale is greater than 1<p>"+
        "     - scales the graph view when the combined scale is less than 1"+

        "</ul>"+
        "<h3>Editing Mode:</h3>"+
        "<ul>"+
        "<li>Left-click an empty area to create a new Vertex"+
        "<li>Left-click on a Vertex and drag to another Vertex to create an Undirected Edge"+
        "<li>Shift+Left-click on a Vertex and drag to another Vertex to create a Directed Edge"+
        "</ul>"+
        "<h3>Picking Mode:</h3>"+
        "<ul>"+
        "<li>Mouse1 on a Vertex selects the vertex"+
        "<li>Mouse1 elsewhere unselects all Vertices"+
        "<li>Mouse1+Shift on a Vertex adds/removes Vertex selection"+
        "<li>Mouse1+drag on a Vertex moves all selected Vertices"+
        "<li>Mouse1+drag elsewhere selects Vertices in a region"+
        "<li>Mouse1+Shift+drag adds selection of Vertices in a new region"+
        "<li>Mouse1+CTRL on a Vertex selects the vertex and centers the display on it"+
        "</ul>"+
        "<h3>Transforming Mode:</h3>"+
        "<ul>"+
        "<li>Mouse1+drag pans the graph"+
        "<li>Mouse1+Shift+drag rotates the graph"+
        "<li>Mouse1+CTRL(or Command)+drag shears the graph"+
        "</ul>"+
        "</html>";
    
    /**
     * create an instance of a simple graph with popup controls to
     * create a graph.
     * 
     */
    public MiniGraph(Controleur ct, String nomCourant, String etape) {
        
        // allows the precise setting of initial vertex locations
    	vertexLocations = new DefaultSettableVertexLocationFunction();
        
        // create a simple graph for the demo
        graph = new SparseGraph();
        
        Hashtable<String, SparseVertex> map = new Hashtable<String, SparseVertex>();
        Hashtable<SparseVertex, Ville> map2 = new Hashtable<SparseVertex, Ville>();
        Hashtable<SparseVertex, Icon> iconMap = new Hashtable<SparseVertex, Icon>();
        Hashtable<String, Ville> villesRecherche = ct.getVilles();
        Hashtable<String, Ville> villes = new Hashtable<String, Ville>();
        Hashtable<AbstractSparseEdge, Troncon> mapEdge = new Hashtable<AbstractSparseEdge, Troncon>();
        Ville villeCourante = villesRecherche.get(nomCourant);
        Ville prochaineVille = villesRecherche.get(etape);
        try {
			for (Troncon troncon:villeCourante.getTroncons()){
				Ville ville1 = troncon.getVille1();
				Ville ville2 = troncon.getVille2();
				villes.put(ville1.getNom(), ville1);
				villes.put(ville2.getNom(), ville2);
			}
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        for (Iterator<Entry<String, Ville>> iterator = villes.entrySet().iterator(); iterator.hasNext();) { 
        	Entry<String, Ville> entry = iterator.next();
        	SparseVertex v = new SparseVertex();
        	graph.addVertex(v);
        	map.put(entry.getValue().getNom(), v);
        	map2.put(v, entry.getValue());

            
            try {
            	Icon petite =  new ImageIcon(GraphEditorDemo.class.getResource("/fleches/petite.gif"));
            	Icon moyenne =  new ImageIcon(GraphEditorDemo.class.getResource("/fleches/moyenne.gif"));
            	Icon grande =  new ImageIcon(GraphEditorDemo.class.getResource("/fleches/grande.gif"));
            	if (entry.getValue().getTaille() != null){
            		if (entry.getValue().getTaille().intitule() == "petite"){
            			iconMap.put(v, petite);
            		}
            		else if (entry.getValue().getTaille().intitule() == "moyenne"){
            			iconMap.put(v, moyenne);
            		}
            		else if (entry.getValue().getTaille().intitule() == "grande"){
            			iconMap.put(v, grande);
            		}
            	}else{
            		iconMap.put(v, petite);
            	}
                
                
            } catch(Exception ex) {
                System.err.println("You need slashdoticons.jar in your classpath to see the image ");
            }
        }
        try {
			for (Troncon troncon:villeCourante.getTroncons()){
				Ville ville1 = troncon.getVille1();
				Ville ville2 = troncon.getVille2();
				SparseVertex vertex1 = map.get(ville1.getNom());
				SparseVertex vertex2 = map.get(ville2.getNom());
				AbstractSparseEdge e;
				if (ville2 == prochaineVille){
					e = new DirectedSparseEdge(vertex1, vertex2);
				}else{
					e = new UndirectedSparseEdge(vertex1, vertex2);
				}
				mapEdge.put(e, troncon);
				graph.addEdge(e);
			}
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
        PluggableRenderer pr = new PluggableRenderer();
        //this.layout = new StaticLayout(graph);
        FRLayout frlayout = new FRLayout(graph);
        frlayout.setMaxIterations(100); 
        frlayout.initialize(new Dimension(250,250));
        vv =  new VisualizationViewer(frlayout, pr);
        for (Iterator<Entry<String, SparseVertex>> iterator = map.entrySet().iterator(); iterator.hasNext();) { 
        	Entry<String, SparseVertex> entry = iterator.next();        	
        	vertexLocations.setLocation(entry.getValue() , frlayout.getLocation(entry.getValue()));
//        	System.out.println(v"Location:");
//        	System.out.println(frlayout.getLocation(entry.getValue()));
//        	System.out.println("Coordinate:");
//        	System.out.println(vv.transform(frlayout.getLocation(entry.getValue())));
        	
        }        
        this.layout = new StaticLayout(graph);
//        this.layout.initialize(new Dimension(600,600));
//        for (Iterator<Entry<String, SparseVertex>> iterator = map.entrySet().iterator(); iterator.hasNext();) { 
//        	Entry<String, SparseVertex> entry = iterator.next();
//        	vertexLocations.setLocation(entry.getValue() , this.layout.getLocation(entry.getValue()));
//        	System.out.println(frlayout.getLocation(entry.getValue()));
//        }
//        vertexLocations.setLocation(map.get("paris"), new Point(0, 0));
        this.layout.initialize(new Dimension(250,250));
        
//        System.out.println("After init : \n");
//        for (Iterator<Entry<String, SparseVertex>> iterator = map.entrySet().iterator(); iterator.hasNext();) { 
//        	Entry<String, SparseVertex> entry = iterator.next();
////        	vertexLocations.setLocation(entry.getValue() , frlayout.getLocation(entry.getValue()));
//        	System.out.println(frlayout.getLocation(entry.getValue()));
//        }  
        final VertexStringerImpl vertexStringerImpl = 
            new VertexStringerImpl(map2);
//        System.out.println(vertexStringerImpl.getLabel(map.get("paris")));
        pr.setVertexStringer(vertexStringerImpl);
        pr.setGraphLabelRenderer(new DefaultGraphLabelRenderer(Color.cyan, Color.cyan));
        
        
        final VertexIconAndShapeFunction vertexImagerAndShapeFunction =
            new VertexIconAndShapeFunction(new EllipseVertexShapeFunction());
        vertexImagerAndShapeFunction.setIconMap(iconMap);
        pr.setVertexShapeFunction(vertexImagerAndShapeFunction);
        pr.setVertexIconFunction(vertexImagerAndShapeFunction);
        
        
        vv =  new VisualizationViewer(frlayout, pr);
        
        vv.setBackground(Color.white);
//        vv.setPickSupport(new ShapePickSupport());
        pr.setEdgeShapeFunction(new EdgeShape.BentLine());
        
    //    pr.setEdge


//        vv.setToolTipFunction(new DefaultToolTipFunction());
        

       
        
//        final EditingMouse graphMouse = new EditingMouse(map2);
//        
//        // the EditingGraphMouse will pass mouse event coordinates to the
//        // vertexLocations function to set the locations of the vertices as
//        // they are created
//        
//        graphMouse.setVertexLocations(vertexLocations);
        vv.setGraphMouse(null);
        vv.getViewTransformer().setScale(0.85, 0.85, frlayout.getLocation(map.get(villeCourante.getNom())));
        vv.getViewTransformer().translate(150, 0);
//        graphMouse.add(new EditingPopupVilleGraphMouse(vertexLocations, map2, iconMap, mapEdge, ct));
//        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
//        
        final ScalingControl scaler = new CrossoverScalingControl();
        JButton plus = new JButton("+");
        plus.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1.1f, vv.getCenter());
            }
        });
//        JButton minus = new JButton("-");
//        minus.addActionListener(new ActionListener() {
//            public void actionPerformed(ActionEvent e) {
//                scaler.scale(vv, 1/1.1f, vv.getCenter());
//            }
//        });
//        
//        JButton help = new JButton("Help");
//        help.addActionListener(new ActionListener() {
//
//            public void actionPerformed(ActionEvent e) {
//                JOptionPane.showMessageDialog(vv, instructions);
//            }});
//
//        JPanel controls = new JPanel();
//        controls.add(plus);
//        controls.add(minus);
////        JComboBox modeBox = graphMouse.getModeComboBox();
////        controls.add(modeBox);
//        controls.add(help);
        
    }
    
    /**
     * copy the visible part of the graph to a file as a jpeg image
     * @param file
     */
    public void writeJPEGImage(File file) {
        int width = vv.getWidth();
        int height = vv.getHeight();

        BufferedImage bi = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = bi.createGraphics();
        vv.paint(graphics);
        graphics.dispose();
        
        try {
            ImageIO.write(bi, "jpeg", file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public int print(java.awt.Graphics graphics,
            java.awt.print.PageFormat pageFormat, int pageIndex)
            throws java.awt.print.PrinterException {
        if (pageIndex > 0) {
            return (Printable.NO_SUCH_PAGE);
        } else {
            java.awt.Graphics2D g2d = (java.awt.Graphics2D) graphics;
            vv.setDoubleBuffered(false);
            g2d.translate(pageFormat.getImageableX(), pageFormat
                    .getImageableY());

            vv.paint(g2d);
            vv.setDoubleBuffered(true);

            return (Printable.PAGE_EXISTS);
        }
    }
    
    /**
     * A simple implementation of VertexStringer that
     * gets Vertex labels from a Map  
     * 
     * @author Tom Nelson - RABA Technologies
     *
     *
     */
    public static class VertexStringerImpl implements VertexStringer {
        
    	Hashtable<SparseVertex, Ville> map = new Hashtable<SparseVertex, Ville>();
        
        boolean enabled = true;
        
        public VertexStringerImpl(Hashtable<SparseVertex, Ville> map) {
            this.map = map;
        }
        
        /* (non-Javadoc)
         * @see edu.uci.ics.jung.graph.decorators.VertexStringer#getLabel(edu.uci.ics.jung.graph.Vertex)
         */
        public String getLabel(ArchetypeVertex v) {
            if(isEnabled()) {
            	if (map.get(v) != null){
            		return (String)map.get(v).getNom();
            	} else {
            		return "marche pas";
            	}
            } else {
                return "";
            }
        }
        
        /**
         * @return Returns the enabled.
         */
        public boolean isEnabled() {
            return enabled;
        }
        
        /**
         * @param enabled The enabled to set.
         */
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }

    
    public static class LayeredIcon extends ImageIcon {

		Set iconSet = new LinkedHashSet();

		public LayeredIcon(Image image) {
		    super(image);
		}

		public void paintIcon(Component c, Graphics g, int x, int y) {
            super.paintIcon(c, g, x, y);
            Dimension d = new Dimension(getIconWidth(), getIconHeight());
			for (Iterator iterator = iconSet.iterator(); iterator.hasNext();) {
				Icon icon = (Icon) iterator.next();
                 Dimension id = new Dimension(icon.getIconWidth(), icon.getIconHeight());
                 int dx = (d.width - id.width)/2;
                 int dy = (d.height - id.height)/2;
				icon.paintIcon(c, g, x+dx, y+dy);
			}
		}

		public void add(Icon icon) {
			iconSet.add(icon);
		}

		public boolean remove(Icon icon) {
			return iconSet.remove(icon);
		}
	}
    
    
    /**
     * a driver for this demo
     */
//	public static void main(String[] args) {
//		Controleur ct = new Controleur();
//	    JFrame frame = new JFrame();
//        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        ct.choisirReseau("/home/chewbie/workspace/roadguide@GoogleCode/exemples/reseau_sujet.xml");
//      //  System.out.println(ct.toString());
//        final MiniGraph demo = new MiniGraph(ct, "paris", "wissous");
//        
//		
//	//	System.out.println(ct.toString());
//        frame.getContentPane().add(demo.vv);
//        frame.pack();
//        frame.setVisible(true);
//	
//		
//	}
}